﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;

namespace EITSurferInfinityLib.DataProcessing
{
    public class ImageReconstruction
    {
        float [] dataRef;
        float[,] RMat;

        float[] dataDiff;
        float[] dataOut;

        int nbNodes;
        int nbMeas;

        public float [] LastReconstructedImage;

        public ImageReconstruction()
        {
        }

        public bool IsReady(ref float[] dataIn, string PathDefaultLibrary)
        {
            bool output=true;
            try
            {
                if (dataRef == null)
                {
                    SetRef(dataIn);
                    if (dataRef == null)
                    {
                        output = false;
                    }
                }

                if (RMat == null)
                {
                    loadMagicMatrix(PathDefaultLibrary);
                    if (RMat == null)
                    {
                        output = false;
                    }
                }
            }
            catch (Exception e)
            {
                output = false;
            }
            return output;
        }

        public void SetRef(float[] refIn)
        {
            if (refIn != null)
            {
                dataRef = new float[refIn.Length];
                for (int i = 0; i < refIn.Length; i++)
                {
                    dataRef[i] = refIn[i];
                }
            }
        }

        public void CalculateNoReturn(float[] dataIn)
        {
            LastReconstructedImage=Calculate(dataIn);
        }

        public float[] Calculate(float[] dataIn)
        {
            dataOut = new float[dataIn.Length];
            dataDiff = new float[dataIn.Length];
            //differential vector
            for (int i = 0; i < dataIn.Length; i++)
            {
                //dataDiff[i] = dataIn[i] - dataRef[i] / ((dataIn[i] + dataRef[i]) / (float)2.0);
                dataDiff[i] = dataIn[i] - dataRef[i];
            }

            ////matrix mul
            //for (int i = 0; i < nbMeas; i++)
            //{
            //    for (int j = 0; j < nbNodes; j++)
            //    {
            //        dataOut[i]=RMat[i,j]*dataDiff[i];
            //    }
            //}

            calculateImage();

            return dataOut;
        }

        private unsafe void calculateImage()
        {
            if (RMat == null)
            {
                //loadMagicMatrix("Mesh lib\\default");
                //loadDefaultShapedMeasurement(ref pb);
                //differentiateDataVector(ref pb);
            }
            else
            {
                Parallel.For(0, nbNodes, i =>
                {
                    fixed (float* a = RMat)
                    fixed (float* b = dataDiff)
                    fixed (float* c = dataOut)
                    {
                        float tmp = c[i];
                        for (int j = nbMeas - 1; j >= 0; j--)
                        {
                            tmp += a[i * nbMeas + j] * b[j];
                        }
                        c[i] = tmp;
                    }
                });

                LastReconstructedImage= new float[nbNodes];

                for (int i = 0; i < LastReconstructedImage.Length; i++)
                {
                    LastReconstructedImage[i] = dataOut[i];
                }
            }
        }

        public void loadMagicMatrix(string path)
        {
            string pathMesh = path + "\\RMn.imat";
            try
            {
                FileStream fs = new FileStream(pathMesh, FileMode.Open);
                BinaryReader br = new BinaryReader(fs);

                int row = br.ReadInt32(); //number of row
                int col = br.ReadInt32(); //number of column

                RMat = new float[row, col];
                nbNodes = row;
                nbMeas = col;

                for (int i = 0; i < row; i++)
                {
                    for (int j = 0; j < col; j++)
                    {
                        try
                        {
                            RMat[i, j] = br.ReadSingle();
                        }
                        catch (Exception e)
                        {

                        }
                    }
                }
                fs.Close();
            }
            catch (Exception e)
            {

            }
        }
    }



}
